package com.yuelao.yuelao_backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuelao.yuelao_backend.common.BizException;
import com.yuelao.yuelao_backend.common.ErrorCode;
import com.yuelao.yuelao_backend.dto.InviteInfoDTO;
import com.yuelao.yuelao_backend.dto.InviteRankingDTO;
import com.yuelao.yuelao_backend.entity.InviteRecord;
import com.yuelao.yuelao_backend.entity.InviteCode;
import com.yuelao.yuelao_backend.entity.User;
import com.yuelao.yuelao_backend.mapper.InviteRecordMapper;
import com.yuelao.yuelao_backend.mapper.InviteCodeMapper;
import com.yuelao.yuelao_backend.service.AchievementService;
import com.yuelao.yuelao_backend.service.CoinService;
import com.yuelao.yuelao_backend.service.InviteService;
import com.yuelao.yuelao_backend.service.UserService;
import com.yuelao.yuelao_backend.service.SystemConfigService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.math.BigDecimal; // 导入 BigDecimal
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.Arrays;
import java.util.stream.Collectors;

@Service
public class InviteServiceImpl extends ServiceImpl<InviteRecordMapper, InviteRecord> implements InviteService {

    @Resource
    private UserService userService;

    @Resource
    private CoinService coinService;
    
    @Resource
    private AchievementService achievementService;

    @Resource
    private InviteCodeMapper inviteCodeMapper;

    @Resource
    private SystemConfigService systemConfigService;

    @Override
    public InviteInfoDTO getInviteInfo(Long userId) {
        User user = userService.getById(userId);
        if (user == null) {
            throw new BizException(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        }

        LambdaQueryWrapper<InviteRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(InviteRecord::getInviterId, userId);
        List<InviteRecord> records = list(queryWrapper);
        int invitedCount = records.size();
        int pendingRewards = records.stream()
                .filter(r -> "completed".equals(r.getStatus()))
                .map(r -> r.getInviterReward() == null ? 0 : r.getInviterReward())
                .reduce(0, Integer::sum);
        int claimedRewards = records.stream()
                .filter(r -> "rewarded".equals(r.getStatus()))
                .map(r -> r.getInviterReward() == null ? 0 : r.getInviterReward())
                .reduce(0, Integer::sum);

        String inviteCode = ensureInviteCode(userId);

        InviteInfoDTO dto = new InviteInfoDTO();
        dto.setUserId(userId);
        dto.setInviteCode(inviteCode);
        dto.setInvitedCount(invitedCount);
        dto.setPendingRewards(pendingRewards);
        dto.setClaimedRewards(claimedRewards);
        return dto;
    }

    @Override
    public String generateInviteLink(Long userId) {
        String code = ensureInviteCode(userId);
        String baseUrl = systemConfigService.getConfigValue("base-url", "https://zddlxy.work/api");
        return baseUrl + "/invite?code=" + code;
    }

    private String ensureInviteCode(Long userId) {
        LambdaQueryWrapper<InviteCode> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(InviteCode::getUserId, userId);
        InviteCode existing = inviteCodeMapper.selectOne(wrapper);
        if (existing != null && existing.getStatus() != null && existing.getStatus() == 1) {
            return existing.getCode();
        }
        String code = generateNewCode();
        // 唯一性校验，极低概率冲突重试一次
        InviteCode conflict = inviteCodeMapper.selectOne(new LambdaQueryWrapper<InviteCode>().eq(InviteCode::getCode, code));
        if (conflict != null) {
            code = generateNewCode();
        }
        InviteCode ic = new InviteCode();
        ic.setUserId(userId);
        ic.setCode(code);
        ic.setTotalInvites(0);
        ic.setValidInvites(0);
        ic.setTotalRewards(0);
        ic.setExpireAt(LocalDateTime.now().plusYears(10));
        ic.setStatus(1);
        ic.setCreatedAt(LocalDateTime.now());
        ic.setUpdatedAt(LocalDateTime.now());
        if (existing == null) {
            inviteCodeMapper.insert(ic);
        } else {
            ic.setId(existing.getId());
            inviteCodeMapper.updateById(ic);
        }
        return code;
    }

    private String generateNewCode() {
        return "I" + UUID.randomUUID().toString().replace("-", "").substring(0, 8).toUpperCase();
    }

    @Override
    @Transactional
    public boolean registerWithInvite(String inviteCode, Long inviteeId) {
        InviteCode inviteCodeEntity = inviteCodeMapper.selectOne(new LambdaQueryWrapper<InviteCode>()
                .eq(InviteCode::getCode, inviteCode)
                .eq(InviteCode::getStatus, 1));
        if (inviteCodeEntity == null) {
            throw new BizException(ErrorCode.PARAMS_ERROR, "无效或过期的邀请码");
        }
        Long inviterId = inviteCodeEntity.getUserId();

        User inviter = userService.getById(inviterId);
        if (inviter == null) {
            throw new BizException(ErrorCode.NOT_FOUND_ERROR, "邀请人不存在");
        }

        User invitee = userService.getById(inviteeId);
        if (invitee == null) {
            throw new BizException(ErrorCode.NOT_FOUND_ERROR, "被邀请人不存在");
        }

        // 检查是否已被邀请过
        LambdaQueryWrapper<InviteRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(InviteRecord::getInviteeId, inviteeId);
        if (count(queryWrapper) > 0) {
            throw new BizException(ErrorCode.OPERATION_ERROR, "该用户已被邀请过");
        }

        InviteRecord record = new InviteRecord();
        record.setInviterId(inviterId);
        record.setInviteeId(inviteeId);
        record.setInviteCode(inviteCode);
        record.setStatus("completed");
        record.setInviteTime(LocalDateTime.now());
        record.setRegisterTime(LocalDateTime.now());
        int inviterReward = parseInt(systemConfigService.getConfigValue("invite.reward.inviter", "500"));
        int inviteeReward = parseInt(systemConfigService.getConfigValue("invite.reward.invitee", "200"));
        record.setInviterReward(inviterReward);
        record.setInviteeReward(inviteeReward);
        boolean saved = save(record);

        // 检查邀请相关成就
        if (saved) {
            achievementService.checkInviteAchievements(inviterId, false);
            // 更新统计
            inviteCodeEntity.setTotalInvites((inviteCodeEntity.getTotalInvites() == null ? 0 : inviteCodeEntity.getTotalInvites()) + 1);
            inviteCodeEntity.setValidInvites((inviteCodeEntity.getValidInvites() == null ? 0 : inviteCodeEntity.getValidInvites()) + 1);
            inviteCodeEntity.setUpdatedAt(LocalDateTime.now());
            inviteCodeMapper.updateById(inviteCodeEntity);
            if (inviteeReward > 0) {
                coinService.addCoins(inviteeId, inviteeReward, "invite", "被邀请奖励",
                        "被邀请注册奖励", record.getId(), "invitee_register_reward");
            }
        }
        
        return saved;
    }

    @Override
    @Transactional
    public boolean claimInviteReward(Long userId, Long inviteRecordId) {
        InviteRecord record = getById(inviteRecordId);
        if (record == null || !record.getInviterId().equals(userId)) {
            throw new BizException(ErrorCode.NOT_FOUND_ERROR, "邀请记录不存在或不属于当前用户");
        }
        if (!"completed".equals(record.getStatus())) {
            throw new BizException(ErrorCode.OPERATION_ERROR, "该奖励已领取或不符合领取条件");
        }

        int rewardCoins = record.getInviterReward() == null
                ? parseInt(systemConfigService.getConfigValue("invite.reward.inviter", "10000"))
                : record.getInviterReward();
        coinService.addCoins(userId, rewardCoins, "invite", "邀请奖励",
            "邀请好友成功奖励", record.getId(), "invite_reward");

        record.setStatus("rewarded");
        record.setRewardClaimTime(LocalDateTime.now());
        boolean updated = updateById(record);
        
        if (updated) {
            achievementService.checkInviteAchievements(userId, true);
            InviteCode code = inviteCodeMapper.selectOne(new LambdaQueryWrapper<InviteCode>()
                    .eq(InviteCode::getUserId, userId));
            if (code != null) {
                int total = code.getTotalRewards() == null ? 0 : code.getTotalRewards();
                code.setTotalRewards(total + rewardCoins);
                code.setUpdatedAt(LocalDateTime.now());
                inviteCodeMapper.updateById(code);
            }
        }
        
        return updated;
    }

    private int parseInt(String v) {
        try {
            return Integer.parseInt(v);
        } catch (Exception e) {
            return 0;
        }
    }

    @Override
    public List<InviteRankingDTO> getInviteRanking(int page, int size) {
        Page<InviteRecord> pageObj = new Page<>(page, size);
        // 统计每个邀请人的邀请数量
        // 实际中可能需要更复杂的SQL查询或缓存
        List<InviteRankingDTO> ranking = baseMapper.selectList(new LambdaQueryWrapper<InviteRecord>()
                        .select(InviteRecord::getInviterId)
                        .groupBy(InviteRecord::getInviterId)
                        .orderByDesc(InviteRecord::getInviterId) // 简单排序，实际按邀请数量
                )
                .stream()
                .map(record -> {
                    InviteRankingDTO dto = new InviteRankingDTO();
                    dto.setUserId(record.getInviterId());
                    // 模拟邀请数量
                    dto.setInviteCount((int) count(new LambdaQueryWrapper<InviteRecord>().eq(InviteRecord::getInviterId, record.getInviterId())));
                    User user = userService.getById(record.getInviterId());
                    if (user != null) {
                        dto.setNickname(user.getBasicInfo().getNickname());
                        dto.setAvatarUrl(user.getBasicInfo().getAvatarUrl());
                    }
                    return dto;
                })
                .sorted((a, b) -> b.getInviteCount() - a.getInviteCount()) // 再次排序确保正确
                .collect(Collectors.toList());

        // 手动分页
        int start = (int) pageObj.offset();
        int end = Math.min((start + (int) pageObj.getSize()), ranking.size());
        if (start > ranking.size()) {
            return new ArrayList<>();
        }
        return ranking.subList(start, end);
    }

    @Override
    public List<String> getInviteEvents() {
        // 模拟邀请活动信息
        return Arrays.asList(
                "邀请新用户注册，双方各获得100爱心币！",
                "邀请用户完成首次充值，邀请人额外获得500爱心币！"
        );
    }
}